home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-06-19 | 8.8 KB | 320 lines | [TEXT/CWIE] |
- /*
- Problem 04 - Text Processing
-
- const
- kMaxHandleSize = 1000000;
- const
- kActionMove = 1;
- kActionInsert = 2;
- kActionDelete = 3;
- kActionSearch = 4;
- kActionSearchAndReplace = 5;
- const
- kFlagCaseSensitiveBit = 0;
- kFlagGlobalBit = 1;
- kFlagBackwardsBit = 2;
- type
- ActionRecord = record
- action: UInt32;
- amount: SInt32;
- flags: UInt32;
- search: Str255;
- replace: Str255;
- end;
- ActionRecordArray = array[0..0] of ActionRecord;
- ActionRecordArrayPtr = ^ActionRecordArray;
-
- procedure TextProcess( data: Handle; action_count: UInt32; actions:
- ActionRecordArrayPtr );
-
- Given an unlocked handle to a block of text, you need to apply a sequence of
- actions to the data. You will be required to insert text, delete text, search
- for text, search for and replace text. All required actions take place at the
- position of the current selection pointer, which starts at zero, before the
- first character in the data. In response to each of the action commands you
- need to perform the following:
-
- kActionMove - move the internal position forward by the amount field (which may
- be negative). (Example, kActionMove with amount set to kMaxHandleSize will set
- the internal pointer to be GetHandleSize( data )).
-
- kActionInsert - Insert the replace string at the current location. (Example,
- if the internal pointer is GetHandleSize( data ), then the replace string will
- be appended to the handle.
-
- kActionDelete - Delete the number of characters specified by the amount field.
- The internal position pointer is never moved. If the amount field is greater
- than the number of characters after the internal pointer, then fewer characters
- are deleted such that the handle is truncated at the current value of the
- selection pointer.
-
- kActionSearch - search forward (backwards if the kFlagBackwardsBit is set in
- the flags field) for the search field (case sensitively if the
- kFlagCaseSenstitiveBit is set in the flags field). The position pointer should
- be set to point before the first character of the string if it is found, or at
- GetHandleSize (zero if backwards) if not found. If there is a match at the
- initial position, it is not counted (ie, kActionMove -kMaxHandleSize, kSearch
- 'hello', kSearch 'hello' finds the second occurance of 'hello').
-
- kActionSearchAndReplace - search forward (or backward if the kFlagBackwardsBit
- is set in the flags field), but when a match is found, replace it with the
- replace string, leaving the position pointer unmoved. If the kFlagGlobalBit is
- set in the flags field, continue searching as long matches continues to be
- found. Repeated searches begin after the previous replace string (i.e., never
- replace any characters of the replace string). For example, if you replace
- 'aaa' with 'ABA' (case insensitively) in 'aaaaaaaa' you will get 'ABAABAaa',
- not 'ABABABAa'. Replace never moves the internal position pointer.
-
- The internal selection pointer is constrained to be in the range of 0 and
- GetHandleSize(data), inclusive, at all times. Should any action cause the
- selection pointer to become less than zero (or greater than GetHandleSize),
- then you must reset it to zero (or GetHandleSize, respectively). The handle
- size will never exceed 1 Meg, and you will have plenty of memory to play with.
-
- Characters from chr(127)-chr(255) will never appear in the handle or any
- strings.
- */
-
- #include "Solution.h"
- #include <string.h>
- #include <ctype.h>
-
- // Fill in your solution and then submit this folder
-
- // Team Name: FILL IN YOUR TEAM NAME!
-
- static void
- DoMove(Handle, const ActionRecord& action, int& selection)
- {
- selection += action.amount;
- }
-
- static void
- SimpleInsert(Handle data, int selection, int amount, const void* insertData)
- {
- int size = GetHandleSize(data);
- SetHandleSize(data, size + amount);
- BlockMove(*data + selection, *data + selection + amount, size - selection);
- BlockMove(insertData, *data + selection, amount);
- }
-
- static void
- DoInsert(Handle data, const ActionRecord& action, int &selection)
- {
- SimpleInsert(data, selection, action.search[0], &action.search[1]);
- //selection += action.search[0];
- }
-
- static void
- SimpleDelete(Handle data, int selection, int amount)
- {
- int size = GetHandleSize(data);
- if (selection + amount > size)
- amount = size - selection;
- BlockMove(*data + selection + amount, *data + selection, size - amount - selection);
- SetHandleSize(data, size - amount);
- }
-
- static void
- DoDelete(Handle data, const ActionRecord& action, int selection)
- {
- SimpleDelete(data, selection, action.amount);
- }
-
- static bool
- MatchCaseInsensitive(const char *a, const char *b, int length)
- {
- while (length-- != 0)
- if (tolower(*a++) != tolower(*b++))
- return false;
- return true;
- }
-
- static bool
- Match(Handle data, const ActionRecord& action, int position)
- {
- if (GetHandleSize(data) - position < action.search[0])
- return false;
- if (action.flags & (1 << kFlagCaseSenstitiveBit))
- return memcmp(*data + position, &action.search[1], action.search[0]) == 0;
- return MatchCaseInsensitive(*data + position, (char *)&action.search[1], action.search[0]);
- }
-
- static void
- Replace(Handle data, const ActionRecord& action, int position)
- {
- SimpleDelete(data, position, action.search[0]);
- SimpleInsert(data, position, action.replace[0], &action.replace[1]);
- }
-
- static void
- DoSearchForward(Handle data, const ActionRecord& action, int& selection)
- {
- while (1) {
- if (selection == GetHandleSize(data))
- return;
- selection += 1;
- if (Match(data, action, selection))
- return;
- }
- }
-
- static void
- DoSearchBackward(Handle data, const ActionRecord& action, int& selection)
- {
- while (1) {
- if (selection == 0)
- return;
- selection -= 1;
- if (Match(data, action, selection))
- return;
- }
- }
-
- static void
- DoSearch(Handle data, const ActionRecord& action, int& selection)
- {
- if (action.flags & (1 << kFlagBackwardsBit))
- DoSearchBackward(data, action, selection);
- else
- DoSearchForward(data, action, selection);
- }
-
- /*
-
- kActionSearchAndReplace - search forward (or backward if the kFlagBackwardsBit
- is set in the flags field), but when a match is found, replace it with the
- replace string, leaving the position pointer unmoved. If the kFlagGlobalBit is
- set in the flags field, continue searching as long matches continues to be
- found. Repeated searches begin after the previous replace string (i.e., never
- replace any characters of the replace string). For example, if you replace
- 'aaa' with 'ABA' (case insensitively) in 'aaaaaaaa' you will get 'ABAABAaa',
- not 'ABABABAa'. Replace never moves the internal position pointer.
-
- */
-
- static void
- DoReplaceForward(Handle data, const ActionRecord& action, int& selection)
- {
- while (1) {
- if (selection >= GetHandleSize(data))
- return;
- selection += 1;
- if (Match(data, action, selection)) {
- Replace(data, action, selection);
- if ((action.flags & (1 << kFlagGlobalBit)) == 0)
- return;
- selection += action.search[0] - 1;
- }
- }
- }
-
- static void
- DoReplaceBackward(Handle data, const ActionRecord& action, int& selection)
- {
- while (1) {
- if (selection <= 0)
- return;
- selection -= 1;
- if (Match(data, action, selection)) {
- Replace(data, action, selection);
- if ((action.flags & (1 << kFlagGlobalBit)) == 0)
- return;
- selection -= action.search[0] - 1;
- }
- }
- }
-
- static void
- DoSearchAndReplace(Handle data, const ActionRecord& action, int& selection)
- {
- if (action.flags & (1 << kFlagBackwardsBit))
- DoReplaceBackward(data, action, selection);
- else
- DoReplaceForward(data, action, selection);
- }
-
- static void
- DumpHandle(Handle data)
- {
- int size = GetHandleSize(data);
- for (int i = 0; i < size; i++) {
- char c((*data)[i]);
- if (c == 13)
- printf("\n");
- else
- printf("%c", c);
- }
- }
-
- static void
- DumpState(Handle data, const ActionRecord& action, int& selection)
- {
- switch (action.action) {
- case kActionMove:
- printf("move");
- break;
-
- case kActionInsert:
- printf("insert");
- break;
-
- case kActionDelete:
- printf("delete");
- break;
-
- case kActionSearch:
- printf("search");
- break;
-
- case kActionSearchAndReplace:
- printf("search and replace");
- break;
- }
- printf(": |");
- DumpHandle(data);
- printf("|\nselection is now %d\n", selection);
- }
-
- static void
- DoAction(Handle data, const ActionRecord& action, int& selection)
- {
- switch (action.action) {
- case kActionMove:
- DoMove(data, action, selection);
- break;
-
- case kActionInsert:
- DoInsert(data, action, selection);
- break;
-
- case kActionDelete:
- DoDelete(data, action, selection);
- break;
-
- case kActionSearch:
- DoSearch(data, action, selection);
- break;
-
- case kActionSearchAndReplace:
- DoSearchAndReplace(data, action, selection);
- break;
- }
-
- if (selection < 0)
- selection = 0;
- if (selection > GetHandleSize(data))
- selection = GetHandleSize(data);
-
- //DumpState(data, action, selection);
- }
-
- pascal void TextProcess( Handle data, UInt32 action_count, ActionRecord *actions )
- {
- //DumpHandle(data);
- //printf("\n");
-
- int selection = 0;
- for (int action = 0; action < action_count; action++)
- DoAction(data, actions[action], selection);
- }